Spark Catalyst & Tungsten System Design
Scenario 1: Catalyst Query Compiler Flow
Problem: Tracing .explain(True) for a high-value user conversion DataFrame query.
Solution:
- Analysis: Uses the Session Catalog to verify table/column existence (
user_id,revenue) and resolve data types. - Logical Optimization: Applies rule-based transformations: Predicate Pushdown (
filter("revenue > 5000")) and Projection Pruning (retaining only required columns). - Physical Planning: Evaluates candidate physical execution plans using the Cost-Based Optimizer (CBO) to select join strategies.
- Code Generation: Compiles the chosen physical plan into flat Java bytecode using Whole-Stage Code Generation.
Scenario 2: Project Tungsten Off-Heap Mechanics
Problem: Explaining why Spark SQL DataFrames run 10x faster than standard Scala RDDs with zero GC pauses.
Solution:
- Off-Heap Memory Storage: Tungsten bypasses the JVM heap, allocating raw binary arrays in off-heap memory via
sun.misc.Unsafe. This avoids JVM object overhead (converting 24-byte Integer objects into 4-byte raw binary values) and completely eliminates Garbage Collection (GC) pauses. - Whole-Stage Code Generation: Flattens nested Volcano iterator function calls (
.next()) into a single localized Java loop that keeps active variables inside high-speed CPU registers and L1/L2 caches.
Scenario 3: Predicate & Projection Pushdown
Problem: Querying an 80GB dataset with df.select("user_id", "channel").filter("channel = 'organic'").distinct().
Solution:
- Projection Pushdown: Pushes column selection directly to the file scanner, skipping the extraction of 48+ unused JSON/Parquet columns.
- Parquet vs CSV/Text: Parquet stores columns independently with Row Group Min/Max metadata, allowing Spark to skip reading entire multi-gigabyte data blocks without parsing a single byte. CSV/Text files require parsing every byte to locate column delimiters.